home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Overload Trio 2
/
Shareware Overload Trio Volume 2 (Chestnut CD-ROM).ISO
/
dir38
/
vgaworm.zip
/
VGAWORMS.C
< prev
next >
Wrap
C/C++ Source or Header
|
1993-10-13
|
10KB
|
259 lines
/****************************************/
/* VGAWORMS.C */
/* (C) Copyright 1993 David Bollinger */
/* send comments to CIS ID# 72510,3623 */
/* compiled with Borland C++ 3.0 */
/* command line: bcc -ms -v- vgaworms.c */
/****************************************/
#include <bios.h>
#include <mem.h>
#include <stdlib.h>
#include <time.h>
#include "vgaworms.h"
#define TRUE (0==0)
#define FALSE (0==1)
#define AND &&
#define OR ||
#define NOT !
#define MAXX 320 // screen x dimension
#define MAXY 200 // screen y dimension
#define MAXWORMS 16 // how many worms (at least 1)
// mainly limited by CPU speed (and memory)
// practical limit of about 50 on 80486
// due to screen clutter
#define MAXSEGS 90 // how many segments in each worm, (max 90)
// if less than 90 not all colors will be used
#define CHANGEDIR 200 // how frequently should the worm change direction
// lower values cause more frequent changes
#define MAXCUSP 30 // how sharp a turn is allowed (0-359)
// smaller values create smoother turns
/********************/
/* global variables */
/********************/
typedef struct
{
int x; // x screen coordinate of this segment
int y; // y screen coordinate of this segment
} WORM[MAXSEGS];
typedef struct
{
int cx; // center x screen coordinate of this worm
int cy; // center y screen coordinate of this worm
int theta; // current angle of rotation of this worm
int tinc; // current rotation direction 1=CCW, -1=CW
int radius; // current radius of path
} DIRECTION;
WORM worms[MAXWORMS];
DIRECTION dirs[MAXWORMS];
char notice[] = "VGAWORMS.C (C) 1993 David Bollinger";
/***********************/
/* function prototypes */
/***********************/
void InitWorms(void);
void InitWormAt(DIRECTION *thisdir, int x, int y);
void UpdateWorms(void);
void DrawWorms(void);
void SetVideoMode(int mode);
void PutPixel(int x, int y, int c);
void SetupPalette(void);
/***************************************************************************/
main()
{
SetVideoMode(19); // 320x200 256 color VGA graphics mode
SetupPalette(); // make a rainbow palette
randomize();
InitWorms(); // set up starting positions
while(bioskey(1)) // chew up any keys waiting in buffer
bioskey(0);
while(NOT bioskey(1)) // do until user presses a key
{
DrawWorms();
UpdateWorms();
}
bioskey(0); // chew up that key
SetVideoMode(3); // return to 80x25 text mode
return 0;
}
/***************************************************************************/
void InitWorms(void)
{
register int worm, seg, x, y;
WORM *thisworm = &worms[0];
DIRECTION *thisdir = &dirs[0];
for (worm=MAXWORMS-1; worm>=0; worm--, thisworm++, thisdir++)
{
/********************************************/
/* pick any point on the screen to start at */
/********************************************/
x = random(MAXX);
y = random(MAXY);
/*******************************************/
/* set each segment to same x,y coordinate */
/*******************************************/
for (seg=MAXSEGS-1; seg>=0; seg--)
{
(*thisworm)[seg].x = x;
(*thisworm)[seg].y = y;
}
/*********************************************************************/
/* set theta and tinc to default values, InitWormAt will change them */
/*********************************************************************/
thisdir->theta = 0;
thisdir->tinc = 1;
InitWormAt(thisdir, x, y);
}
}
/***************************************************************************/
void InitWormAt(DIRECTION *thisdir, int x, int y)
{
int inc;
/********************************************************************/
/* pick a new radius at random, the size limit 10-50 is a practical */
/* limit based on the resolution of the trig tables and screen. */
/* More than 50 causes holes to appear in the worms, while values */
/* less than 10 cause the worm to scrunch up into a little ball */
/********************************************************************/
thisdir->radius = random(40)+10;
/********************************************************************/
/* pick a new angle, use the complementary angle (Θ+180) and add in */
/* and extra 360 to make sure that the result is positive, then add */
/* in a random amount - the larger this random amount the "sharper" */
/* the turn will be. Finally change the rotation direction. */
/********************************************************************/
inc = random(MAXCUSP)-(MAXCUSP/2);
thisdir->theta = (thisdir->theta + 540 + inc) % 360;
thisdir->tinc = -thisdir->tinc;
/***********************************/
/* figure out the new center point */
/***********************************/
thisdir->cx = ((x - (thisdir->radius * sintable[thisdir->theta])/128) + MAXX) % MAXX;
thisdir->cy = ((y - (thisdir->radius * costable[thisdir->theta])/128) + MAXY) % MAXY;
}
/***************************************************************************/
/* moves each segment of all worms to a new position */
/*****************************************************/
void UpdateWorms(void)
{
register int worm;
WORM *thisworm = &worms[0];
DIRECTION *thisdir = &dirs[0];
for(worm=MAXWORMS-1; worm>=0; worm--, thisworm++, thisdir++)
{
/*********************************************/
/* is it time for a random direction change? */
/*********************************************/
if (random(CHANGEDIR)==0)
InitWormAt(thisdir, (*thisworm)[0].x, (*thisworm)[0].y);
/*****************************************************/
/* each ball (except first) moves forward 1 position */
/*****************************************************/
memmove((void *)(&(*thisworm)[1].x), (void *)(&(*thisworm)[0].x), sizeof(WORM)-4);
/**********************************************/
/* now find a new position for the first ball */
/**********************************************/
(*thisworm)[0].x = ((thisdir->cx + ((thisdir->radius * sintable[thisdir->theta])>>7)) + MAXX) % MAXX;
(*thisworm)[0].y = ((thisdir->cy + ((thisdir->radius * costable[thisdir->theta])>>7)) + MAXY) % MAXY;
/*****************************************/
/* move to the next position on the path */
/*****************************************/
thisdir->theta = (thisdir->theta + thisdir->tinc + 360) % 360;
}
}
/***************************************************************************/
/* draw each ball of each set - last ball draws in color 0 to erase tail */
/*************************************************************************/
void DrawWorms(void)
{
register int seg, worm;
WORM *thisworm = &worms[0];
for (worm=MAXWORMS-1; worm>=0; worm--, thisworm++)
for (seg=MAXSEGS-1; seg>=0; seg--)
PutPixel((*thisworm)[seg].x, (*thisworm)[seg].y, MAXSEGS-1-seg);
}
/***************************************************************************/
/* BIOS call to set video mode */
/*******************************/
void SetVideoMode(int mode)
{
asm mov ah, 0
asm mov al, byte ptr mode
asm int 10h
}
/***************************************************************************/
/* direct video access to screen to plot a single pixel */
/* destroys ax, bx, es */
/********************************************************/
void PutPixel(int x, int y, int c)
{
asm mov ax, 0xa000
asm mov es, ax
asm mov bx, word ptr y
asm shl bx, 1
asm mov ax, word ptr ytable[bx]
asm add ax, word ptr x
asm mov bx, ax
asm mov ax, word ptr c
asm mov byte ptr es:[bx], al
}
/***************************************************************************/
/* make a nice smooth rainbow palette */
/* destroys ax, bx, cx, dx, es */
/**************************************/
void SetupPalette(void)
{
asm mov ax, SEG palette // get segment of palette
asm mov es, ax
asm mov dx, OFFSET palette // get offset of palette
asm mov bx, 0 // start with color # 0
asm mov cx, 90 // load 90 colors
asm mov ax, 0x1012 // bios function 10 subfunction 12
asm int 0x10 // call bios to load palette
}
/***************************************************************************/
/***************************************************************************
Trig review: .....
... ...
. .o (x, y)
. r / |.
. / | .
/ Θ ┌| .
(cx, cy) o------- .
.
x = cx + rsinΘ ==> cx = x - rsinΘ
y = cy + rcosΘ ==> cy = y - rcosΘ
***************************************************************************/
/* end of vgaworms.c */